// ==UserScript==
// @name           BB.com forum codes helper
// @namespace      http://code.google.com/p/blitzbasic-forum-enhancements/
// @description    Adds enhancements to the post textarea on blitzbasic.com
// @include        http://blitzmax.com/*
// @include        http://blitzbasic.com/*
// @include        http://www.blitzmax.com/*
// @include        http://www.blitzbasic.com/*
// 
// @exclude        http://blitzmax.com/Account/*
// @exclude        http://blitzbasic.com/Account/*
// @exclude        http://www.blitzmax.com/Account/*
// @exclude        http://www.blitzbasic.com/Account/*
// ==/UserScript==

/**
 * Written 23rd May 2008 by Kris Kelly
 * Modified 8th June 2008 by Kris Kelly
 * Status: Beta
 * Version: 0.7.38
 ***/

/*
 * YUI stuff from http://yuiblog.com/blog/2007/01/03/yui-greasemonkey/
 * */

// Settings used by the loader
var GM_YUILOADER_CONFIG = {
    // List of JS libraries and CSS files to load. obj is used for the object
    // detection used in the loader. Basically, if the object already exists,
    // the script is not injected in the page.
    assets: [
        { type: 'css', url: 'http://yui.yahooapis.com/2.5.1/build/container/assets/container.css' },
        //{ type: 'css', url: 'http://yui.yahooapis.com/2.5.1/build/button/assets/skins/sam/button.css' },
        { type: 'js', obj: 'YAHOO', url: 'http://yui.yahooapis.com/2.5.1/build/utilities/utilities.js' },/*
        { type: 'js', obj: 'YAHOO.util.Dom', url: 'http://yui.yahooapis.com/2.5.1/build/utilities/utilities.js' },
        { type: 'js', obj: 'YAHOO.util.Event', url: 'http://yui.yahooapis.com/2.5.1/build/utilities/utilities.js' },
        { type: 'js', obj: 'YAHOO.util.DragDropMgr', url: 'http://yui.yahooapis.com/2.5.1/build/utilities/utilities.js' },
        { type: 'js', obj: 'YAHOO.util.Anim', url: 'http://yui.yahooapis.com/2.5.1/build/utilities/utilities.js' },*/
        { type: 'js', obj: 'YAHOO.widget.Button', url: 'http://yui.yahooapis.com/2.5.1/build/button/button-min.js' },
        { type: 'js', obj: 'YAHOO.widget.Panel', url: 'http://yui.yahooapis.com/2.5.1/build/container/container-min.js' }
    ],

    // What should be the max allowed loading time? In this example, the
    // script has 6 seconds to load the libraries and CSS files.
    timeout: 15000,

    // How often should the script check if everything was loaded?
    interval: 300,

    // What to trigger once all assets are loaded (a string). Example: execute
    // YBFLOOKUP.run() (this will be eval()'ed later on, hence the string)
    runFunction: 'bbfch_init();',
}

// START LOADER CODE //////////////////////////////////////////////////////////

var YAHOO;
var GM_YUILOADER = {
    // Version of the loader
    VERSION: 20080527,

    // Simple internal timer to keep track of the passed time.
    loaderTimer: 0,
};


// This function checks whether everything was loaded yet; if not, it'll wait
// some more and call itself again. It'll do so until either all assets are
// loaded or the max loading time (GM_YUILOADER.loaderTimer.timeout) is
// reached.

GM_YUILOADER.loaderCheck = function() {
    var ud = unsafeWindow.document;

    // Do we have a green light yet?
    if (ud.GM_YUILOADER_DOC.go) {
        YAHOO = unsafeWindow.YAHOO;
        delete ud.GM_YUILOADER_DOC;
        GM_YUILOADER.run();
    }
    // Nope, not yet. Rinse & repeat!
    else {
        GM_YUILOADER.loaderTimer += GM_YUILOADER_CONFIG.interval;

        if (GM_YUILOADER.loaderTimer >= GM_YUILOADER_CONFIG.timeout) {
            return;
        }

        setTimeout(GM_YUILOADER.loaderCheck, GM_YUILOADER_CONFIG.interval);
    }
}


// Main function that initiates loading the external JS and/or CSS files

GM_YUILOADER.loader = function() {
    if (document.contentType != 'text/html' || !document.body) { return; }

    var ud = unsafeWindow.document;

    // This object holds the important stuff to make this work. It's a property
    // of GM's unsafeWindow.document object.

    ud.GM_YUILOADER_DOC = {
        // Number of JS libraries loaded so far (increased by countLoaded()
        // below)
        numberLoaded: 0,

        // Total number of JS files.
        numberTotal: 0,

        // If this is bool true, we're good to go! This is checked by
        // GM_YUILOADER.loaderCheck().
        go: false,

        // This function will be called by the onLoad events.
        countLoaded: function() {
            if (++this.numberLoaded == this.numberTotal) { this.go = true; }
        }
    };

    // Now let's add the extra tags to the page that'll load the libraries and
    // CSS files.

    var numAssets = GM_YUILOADER_CONFIG.assets.length;

    for (var a = 0; a < numAssets; a++) {
        var tag;
        var asset = GM_YUILOADER_CONFIG.assets[a];

        switch (asset.type) {
            // CSS file
            case 'css':
                tag = document.createElement('link');
                tag.href = asset.url;
                tag.type = 'text/css';
                tag.rel = 'stylesheet';
                break;

            // Javascript library.
            case 'js':
                var injectScript = true;

                // Object detection
                try {
                    injectScript = eval('window.' + asset.obj + ' === undefined');
                }
                catch (e) {}

                if (injectScript) {
                    tag = document.createElement('script');
                    tag.src = asset.url;

                    // The crucial part: triggering document.GM_YUILOADER.countLoaded()
                    // means keeping track whether all scripts are loaded yet.

                    tag.setAttribute('onload', 'document.GM_YUILOADER_DOC.countLoaded();');

                    // How many JS libraries are we dealing with again? Let's keep
                    // track.

                    ud.GM_YUILOADER_DOC.numberTotal++;
                }
                break;
        }

        document.body.appendChild(tag);
    }

    // Did we actually include anything in the page? If so, trigger the
    // GM_YUILOADER.loaderCheck "watchdog". If not, just tell it to run the
    // main part of the script.

    if (ud.GM_YUILOADER_DOC.numberTotal > 0) {
        setTimeout(GM_YUILOADER.loaderCheck, GM_YUILOADER_CONFIG.interval);
    }
    else {
        ud.GM_YUILOADER_DOC.go = true;
        GM_YUILOADER.loaderCheck();
    }
}

GM_YUILOADER.run = function() {
    // When we're here, we're good to go!
    eval(GM_YUILOADER_CONFIG.runFunction);
}


// The initial GM_YUILOADER trigger.
setTimeout(GM_YUILOADER.loader, 500);

// END LOADER CODE ////////////////////////////////////////////////////////////



var pert;

function bbfch_init(){
	YAHOO.namespace("pert");
	pert = YAHOO.pert;
	
	//use http://software.hixie.ch/utilities/cgi/data/data to create a new image
	pert.toggleImage = document.createElement('img');
		pert.toggleImage.src = "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%20%08%06%00%00%00%1B%89%F8%CC%00%00%00%04gAMA%00%00%AF%C87%05%8A%E9%00%00%00%19tEXtSoftware%00Adobe%20ImageReadyq%C9e%3C%00%00%02%07IDATx%DA%DCT%BFk%15A%10%FE.%B9G%F2%C0%F7%82%10%D4H%1Am%AD%04%3B%B55%60g!%F8%0FX%A6%B1%88%85B%B0P%EC-l-%B5%B2%B3%D2B%08)%D2%05%EC%84%14%22%FE%80%13%5E%EEv%EF%D7%FErf.%A7%91%BB%26%97%22%929%96%DD%BB%B9%F9%E6%9B%9D%DD%2F%0A!%E086%87cZ%7C%F8%E5%E3%CE%A70%17E%B2%F6%3E%C0%13%3Bf%C8k%EB%1CjcQU%06wo_%8F%DA%98%A8-%E1%C3%F6n8%7Bf%01%E7%96%16%C0_B%F0%08%BE%F15%20%0E%8E%40%F6%BE%A7%F8%F23%C5%FD%7Bk%D1%3F%25p%96%E5%C9%88f%0FO%3F%3A%EB%B0%BE%B1%89%8D%CD%E7%B4%B6%B04x%5EY%8A%91%A5%B3n%09L%91%83%83%D0%F6%B2%1E%8F%C78%BF%B2J%3E%2B%A0%C6%18%CCf%FB%D0*%EB%02%18%DBPl%83y%CC%C7%23L%A6S%C9%5C%96%25%D2%2C%83%CA%14%8A%5Cw%01%9C%E3%9A%3D%1E%3C~*%99%25x2EL%F3%9Bw%5B%F8%F1%ED%2B%B2%2C%C5%9D%5B7P%D7U%17%40%A8%D3%D3%D2%E6%CC%1C%BC%B88%16%FF%85%8B%ABX%B6%E6O%A9%DD%3D%B0%8D%E3%C9%C3u%99%EB%BA%C6%DB%F7%3B%E2%BBy%F52%D5%AD%91)%05E%C3%90%AF%03%C0%3D%E6Zy%A3%F2%3C%A7Q%08m%CE%9C%24%BF%E8%5DC%EB%1C%05%EDEo%09%0C%A0(%8B%A2%1DVZ%0B%00%D7%CC%B4%93%24%A1%C0%02UYI%02%D3%07%C0%AD%D9%FD%9C%60%3A2%02%94%179%AE%5D%B9D%ED%AB%08%40SV%23g!IKb%FA%F7%FED%87%2F%D3%A3g%2F%82J%F7%85nE%19-e%97%B3q%D0V%B6%F98%C6%EBW%2F%A3%5E%80%13%B9%8D'%0F%F0%9F%EB%01%078g%87%EBA%CB%C0%07%3FL%0F%C2%C1%E1a%D0Az%D0gG%D2%83%3E%3B%92%1Ep%CD%DC%A4%DA%D4%C3%F4%80%03%99%19%DF%C4Az%C0%2C%18%80A%07%E9%811%8D%9C%F3%198%C5z%F0%5B%80%01%00%CB%F3%9C%EA%13%AE%9Cs%00%00%00%00IEND%AEB%60%82";
	pert.jumpLinkImage = document.createElement('img');
		pert.jumpLinkImage.src = "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%10%08%06%00%00%00%1F%F3%FFa%00%00%00%04gAMA%00%00%AF%C87%05%8A%E9%00%00%00%19tEXtSoftware%00Adobe%20ImageReadyq%C9e%3C%00%00%01%CBIDATx%DA%C4S%BDk%15A%10%FFmrG%F2%C0%7B%F1%11%D1%24%3E%C4J%7B%3B%11lR%F8%016B%C0%D2%C6%D2N%5E%23%12%2B%15%5B%0B%5BKK%FF%81%146%16Z%05%EC%04%0B%11%3F%C8%5D%DE%7B%F7%7D%B7%7B%BB%CE%CCy%F8%C2%A5K%E1%1C%C3%CE%ED%EE%FC%E673%3B%CA9%87%93%C8%12N(%DE%E2%CF%FB%8F%9F%DD%92Rb%5B%EB%60%89%1D3d%DB4%0DjmPU%1A%3B%B7%AF%A9%CEGu)%EC%7D%D8w%A3S%2B8%BB%B6%02%DEq%CE%C2%D9%F6%AC%05i%D0%10%C8%D7%9F1%BE%FD%8E%F1%E0%DE%0Du%24%05%8Er%26%F0i%B5%B0t%B11%0D%1ENv1%D9%7DA%B6%81!%E5us%CDC%12%CF%FA)0EvvB%DB%8A%3D%18%0CpnsLgF%40%B5%D6%98%CD%E6%C8%D2%A4%0F%A0MK%B1sf%5D%F6%7C%04%C3%A1D.%CB%12q%92%20MR%14y%D6%07h%1A%CE%99%1C%3B%00%02%EB%A4%AA*%E4y%8E%A2(D%EB%BA%EA%03%08u%FA%1E%3Dy.%D4%25z0%84G%EB%BB%BDO%F8%F5%E3%3B%92%24%C6%9D%ED%AB%12%A0%F7%0E%8Cik%F0%F2%E9%04%A7G%EB%18_%B8%88%8D%AD1VW%07%A2l%DF%BDy%5D%D8%E8%BA%EE%03p%8F9W%BEp%7F%E7%96%EC%B1%A3%E7%FB%A2%97%CF%07%98N%A7R%87%C5%14%8E%00%A4i%86(%8Ap%10%86%B8ri%8B%1C%22%18%AA%FC%C8%CB%11%1D%1Eb%3E%E7%0E%A4%C4%E0%98%1Apk%F6%BF%84%18%FAZ%80%F2%22%C7F%A0%60%AB%03%84%99%A1%A8Z%DEB%18%97%C4%F4%DF%FC%A8%C5az%FC%EC%95K%E39U%3CCU%16%E4%A0%DB%B7%F1%B7%AD%2C%CB%9E%87%B7o%5E%ABc%01%FE%CB4%FE%11%60%00%11%E6%3C5%1D%F08%19%00%00%00%00IEND%AEB%60%82";
	pert.toggleBarButtonImage = document.createElement('img');
		pert.toggleBarButtonImage.src = "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%3E%00%00%00%0C%08%06%00%00%00%3As%0E%E2%00%00%00%04gAMA%00%00%AF%C87%05%8A%E9%00%00%00%19tEXtSoftware%00Adobe%20ImageReadyq%C9e%3C%00%00%02%2CIDATx%DA%DC%96%3F%88%13A%14%87%7F%9B%9D%9C%97%C3%BB%B0%C9%E9%82bio%A1v%96%0A6%16%82v66%16%16*6*b!'%D7%9C%20%82w6%82%1E%88%16b%23W%5E)%96%A2x%82%086'%92%C8m%B2%BB%D9%DD%EC%DFy%BE%99DA%D0%CE%09%98%07%C3%26%CC%C0%F2%CD%7B%BF%2F%B16_%BF%A3%9A%5D%83eA%17I%02a%BAJJ%89%B2%AC%90%17%25%B2%BC%C00%CD!%F2%B2%C4%91%83%FB%7F%1D%22b%EC)%23W%AD%24%86%97%E3%F5r%F3-D%9A%E5%A8%F86t%9Fi%04n%AA%E7%17.%5DC%A3%D1%80-%EA%7F%DC%BF%BBt%C3%109i%E0A%14!%08%02x%3B%5D%88%24%C9PV%A5%BE%91%3C%CF%91%24%09%0A%9E%02u%F8_%D7%ED%EB%97%B1%F6%E4%05%9AN%0B%F5%FA%EF%F0gN%1EC%B7%D31%C0L%3C%E2%05%928F%1C'%3C%E6C%F4%7B%1E%AC%D5%F5W%E4%CC%D5%E06%05%22%DE%D4%E0%7C%D0t%7D%FE6%C0%ECl%03%07Z%C2x%BE%15O%C6%93%AD%9E%DB%5D%1F%FD(%85%08%FC%9E%F5u%3B%A07a%C0%D012%BE%91%B2%2C%B4%E4%26Q%EF'%98oU%B6%10x%FEx%CD%12G%0F%1F%82%CDV%AF%8D%B5.%19X%D2%F4%D8%8Dt%BE%89%E3%3C%B6z6%9AfQU%92%DA%0B%3CrnS%C7Z%5B%1D%E6%CD~%FE%E2U-%BA%07%2BK%13%B4%3A%E1%E3%97%0E%1E%3E%DD%20m%F5%7Dm%97%C7%BB%1C%19%7DDo%8C%FB%A7%D9%17%F7%B8pZm%2C%DF%7F%A4es%E7%E6%15%93m%D7%D0)%C7%B85G%E8%ED%7Cg%AB%0F%B3Q%A6y%B3%E0Q%D09g%BB%9B%B0%FA%AD%E5%7Bp%9C6%16%F7%BA%D8%3D%BF%A0%E5%A6J%7D%5EY%5D%C7%B9%D3'%8Cp%2B.e%F34M%F5%F2%FB%1E%C4%20%1E%C2%F3%3C%F8~%800%0C%F9%B7n%60%CC%EAgO%1D%FF%CB%CE%BC%5E%1F%B6%B6%8C%BCW%FDk%2B%8A%5C%3FU%83%C3%C0%87Pm%7F%B6%F1%09%11%5B%3Dfhe%F5%AA%AA%C6Y%FF%FF%CBbiK%92%3A%E3%FC%8D%ADncff%17~%080%00%95%C5m%09%DC%FA%F7%DE%00%00%00%00IEND%AEB%60%82";
	pert.toggleBarButtonImageMed = document.createElement('img');
		pert.toggleBarButtonImageMed.src = "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%3E%00%00%00%12%08%06%00%00%00%03%AFm%09%00%00%00%04gAMA%00%00%AF%C87%05%8A%E9%00%00%00%19tEXtSoftware%00Adobe%20ImageReadyq%C9e%3C%00%00%031IDATx%DA%DCWKh%13Q%14%3D%93%99%D6%A6i%FAI%FA%B1%B5%DD%08%AD%20EZTD%F0%B3%10%17%AE%DC%B8p%ADK%5D%BA%B6-.D%DC(%14*%08%A2%B8)%88%1B%3F%A0%88%16E%C4%5D)H%A0%82%B6.%14%9B%B4%CDd%FE3o2%E3%7Do%26%90B%97%7D%15z%C3%CB%7C%5E%C8%E4%BCs%DF9'%CA%FB%2FK%B1%9A%C9%40Q%14%C4%FC%15%83%06%BD%ED%A1%8A%A2%08aX%07%A3%E1%FB%0C%8E%E7C%8B%A2%18%13%A3%03%E9G%12%E0%D8c%C0%05%A1%84%93%2F%40%14%D5%F1%E2%E37h%F5z%9DpF%7C6e%5C%9CH%A9%AB%D7o%20%9B%CDB%D5Z%B6%9D%BF%7F%FB%A64%E0%09%E8%08%81%EF%C34j%D08%FD%FC%C6V%E0r%90%9F%3B%7B%0A%DFW%7F%A3%B3%AB%1B%19%DA%5E%CD5~%E8%A0%60c%E7A'%1D%CC1%BA%AE%8B%CD%CD*LS%87%E6Q%CFs%D6%F9d%DC4d%D4%A5%8B%17%F0%E0%C93%14%7B%7B%E1%87%B1%D0%95%7C.%2B%9Ew%E6%C4%04%ED%C3p%E7%81%D3w%FB%C4%B2a%18%A8%F1Q%AB%A1%A6W9%F0%00%11%01%0F%82%00%B6m%C3q%5Cq.%ABNN%1E%86%AA%AA%F8%BC%B8%8C%F6%F6%1CF%87%8Bb%AB%AD%AE%FE%92%D3%E6%04%DC%F3%3CX%B6%05%DB%22%7C%AECG%13%9A%1F0ll%EA%F0%E8%06%9Ftl%07%BED%E0%8D%AA%94%FFb%60%FF%10%8CZU%5C%9B%86%24a%A3%16%E7x%1C%C7%16%0B%E0%BA%3EB%C6%A09%B65%B3X%B2%A6%FA%F2%1A%0Czz%83q%D9%96616%2C%8E%E5rY%BA%951%02%CA%DB%9Do%A5%3F%EB%06%EF%F0%19%E5%CE%ECSZm%3D69hj%01%9FV%85%85%81%90%FF%BDce%89%A2%03%0A9%8A%8A%F9%C7s%8Avl%F2%08%5Dd%90!%A1IV(%15%B8%BD%E2%E1%A9%A2s%F7b%2C%04%17s%5E%1AA%9C.%E4%B3%18%EE%EFlJm%F2%BC%7C%F7%19O%ED%8C%04%943_ZY%C3%C3%F9%B7%D3%3C%B9M%F5%F7%E4%04%D3%90lg%DB%85%99%D9%BB%B7v%87%F5%14%F8H_%1EK%A5%9FSZHV%A6f%90%86%98XX%8BL%E0%E5%CA%BA8r%2B%1B%18%3C%40%8ER%A5%1C%11%A2%B7X%90%CB8%11%CBE%CE%B6%CD%86%9D%85%C2%C7%93UI%84%40%26%F0%7Bs%8F%04%D3%DD%85%22%BA%7B%0Ax%BD%F0%15%1B%952%AE%5D%B9%2C%ED%99%8D%8CbZ%16%2C%1A%A6I%91%D5%F3%02p%D69%601aZB%FAe%D4%9B%0F%9F%E0%92%B8tt%15%D1C%B1%B5%AD-%8B%80EP%5B%B3x%FE%EA%1D%8E%8E%8F%C9%01%CE%02%CA)%1EY%B5%23%BC%5Cdu%8FV%C3%A5%1B%8DH%C7%81%07%8CI%F9%01%A5%E5%1F%18%1C%1A%A1%C8%DA%87%7D%04ZI%9D%A4%23%DF%09%DDv%B1%26%C9%D3%C3%90%09%C0%9C%F9%80%02%5B%10%F8%3C%C0%D8%B4%EF*%D0%AB%BA%080%16%C5%3A%26%09%F8%F9%D3%C7%9Bv%9E%B3u2'%2F%CCp%0D%F1y4%17%5E%8E%24%B9%195%1D%2F%17V%04%FD%8Ec%89%00S%97%F0g%E1%FF%7By%5Dt%98%AAjhim%C5%3F%01%06%00%1D%D1bo%B9%E9p%99%00%00%00%00IEND%AEB%60%82";
	pert.toggleBarButtonImageMed_h = document.createElement('img'); 
		pert.toggleBarButtonImageMed_h.src = "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%12%00%00%00%3E%08%06%00%00%00%26%A0K%1A%00%00%00%04gAMA%00%00%AF%C87%05%8A%E9%00%00%00%19tEXtSoftware%00Adobe%20ImageReadyq%C9e%3C%00%00%03EIDATx%DA%ECX%3BhTA%14%3D%EF%EDK%CC%E6c6%BB%1B%92%AC%A6%08%82)D%10%B1%90%D8Z%D9X%09%D6%166%16%96%16%01%B3%01%09V%11%B10e%EC%14A%F0%83%82A4(%22i%8C%90B0%22%81%20%B2%BB%D9%CF%DB%F7%FF%8D%F7%CE~%8ClV%82%85%20%BC%0B%93%19f%CE%3B%F7%DE%09%CB%BDg%94W%EF%3F%89%84%AABQ%14%08!%10%84!%3C%3F%80%EF%87p%3D%7F%FE%C2%B93y%90%AD%AEm%E4UE%9D%03%04%C20%92%18%1E%AE%EB%C3r%5C(%2B%EF%D6%C5%C9%E9%1C%1A%26%10E%02%22%8A%98%04%9B%DB%25%7C%DD%DE%C1%D4%E11%8C%8E%0C%60%3C%3D%88DB%25%87%11%E1h%84%3C%87x%B2%BA%015%A4%0D%3E%E0%8F%F9%90%E7%90%0E%09%8F%23%B9%14%EAz%0D%8C%C9e%87%A0%AAJ%1B%17Q%E4L%E2y%9E%C4hA%10%CA(8%1AN-j%02%7D%8A%A8V%AB%C1%AC%EB2%5DvF%906%26%94%18%0F%E5r%19%A6%A9%13%11%838%92%16%11%85%EB86%F4z%1D%BA%AE%C3%B2M%B03%115%CF%9Bi%D9%96%25%1D%F1%E0%B5%26%D3%11%A29%1Ai%9A%A6%05%CB4a%11%C0s%1Cy%B9%91h%E2%9Aw(1%96MN%5D%19%99%8A%3D%AC%E1%B5%F1Q%D4%8C%16%8D%EC%5B%7F%1A%7B%BBlO%A2%BF%B1%98(%26%8A%89b%A2%98%E8%DF%11%5D%BEz%0D%0F%1E%3D%DB%F7%87%8F%9F%AF%E0%D6%D2r'Q2%99%C4%97%AD%EFX%BA%F7%10%95%AA%DE%95%A0P%2C%E1%FA%C2%22%3Eona%227%D9%DE%D7Z%8B%84%D6%83%83%C3)d%B2YZ'%A8%26E%5D%A8%14%E9tp8C%D8%D1N%22%19%1Eu%25n%20%F0%F2%EDG%14%0B%3Fp%FE%EC%CCo%14%9C~%7F%FF%00R%E9%0CF%C8%E9%81%BE%E4%DED%D2%1F%B57%0C%1E%1B%CFu%C4%C2%91%8CM%1CBj%24%8D%3E%22alW%A2%A1%81%24NLO%22%F4%A9%CB%A0%FA%BF%DBn%DF%CC%A3%5C%AD%E2%C5%9B5%EA%8D%A2%3F%FF%FB%1B%8D%82%E8z%D9a%10%60%A7X%A0%BAoJ%EC%9ED%C7%8EN%D1%BD%9C%C6%60%7F_W%A2l%26%8D%2B%97.%227%3A%0C%97%BA%96%8E%D4%16o%CC%B6%3B%B1%FD%D8%CC%A9%E3%D4%60%D5%DB%E9%C7%3F%DA%98(%26%8A%89b%A2%FF%98%A8%25KYi%87MQ%2C%DA%CAQ%B41%1DD%ACW%7F%E9Y%01%83%B4%ACQ7H%D3Z0%A9v%F9T(%7D%16%C7%A2%A5%C2%05%ED%5B%B0m%D6%B3%0El%A9y%03h%FC%9A%C0%FA%DD%A7%D90%EA%D8!%F9-%25%B8a%12%C8%A6%DA%E5%C83.S%AE%EB%92(6IY%EB%A8R%C5%B5%EC%86%40v%5D%87%88%BC%40%AAi%96%DD%2C%CF%99%88A%EC%CD%23%ED%1F%04%BE%7C%95%E03%96%F0%A6a%A0%C6k%1AL%CCN%02%DF%87%C6%A5%B7X*%A1Z%A9R_D%A3R%A1%C8%0C8%AE%87B%C5%20%22%8A%B4%AE%E3%C3%BA%8ETR%91o%02%1C%B9a%98%F2%8C%8DgM%AFU%F1%F4%F57%AA%9AU%E9%CD%E6%7B%F1%5C(%D4%E2%244m%FE%FE%F2%5D%F9%C82%BBp'o%E8%B59v%ECPJ%1EE%C3%97%9FHh%E8%E9%ED%C5O%01%06%00%02%98%7C%EF%BE%03%AEl%00%00%00%00IEND%AEB%60%82";
	pert.bottomShadowImage = document.createElement('img');
		pert.bottomShadowImage.src = "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%40%00%00%00%06%08%06%00%00%00sh%98%AF%00%00%00%04gAMA%00%00%AF%C87%05%8A%E9%00%00%00%19tEXtSoftware%00Adobe%20ImageReadyq%C9e%3C%00%00%00RIDATx%DA%E4%D0%C9%11%800%0CCQ%9B%B5%05%FA%EF2%04l%FEA9%D1A%AC%99%A7%BB%E4fv%E1%C4%8E%15%8B%CD%9D%C0%8B%8E%B6Q7%12%8F%C6W8%20%B4%B7%8F%03B%8F%CC%3E%FEw%82S%87%86%BBTHJX%F5xf%96%3E%E0%13%60%00%C1%24%17%00%A8Ge%D6%00%00%00%00IEND%AEB%60%82";
	
	pert.constants = {
		TT_ENCLOSING : 0,
		TT_SELFCLOSING : 1,
		dbOK: 0,
		dbOKCancel: 1,
		dbYesNo: 2
	};
	pert.statics = {//pseudo-statics
		buttonCount:0,
		version:"0.6.32"
	};
	
	pert.config = {};
	
	pert.dialogueConfig = {
		styles: {
			//width: "50%",
			//height: "20%",
			minWidth: "50%",
			opacity: "0.0",
			backgroundColor: "#585f69",
			borderBottom: "1px solid #141A25",
			padding: "1em",
			position: "absolute",
			left: "25%"
		},
		timeout: 5000
	};
		
	
	pert.topicWatchList = {
		topicIds: [],
		topicTitles: [],
		numPosts: [],
		postAgeNums: [],
		postAgeUnits: [],
		lastViewNumPosts: [],
		addTopic:function( obj ){
			this.topicIds.push( obj.details.topicId );
			this.topicTitles.push( obj.details.topicTitle );
			this.numPosts.push( obj.details.numPosts );
			this.postAgeNums.push( obj.details.postAgeNum );
			this.postAgeUnits.push( obj.details.postAgeUnit );
			this.lastViewNumPosts.push( obj.details.numPosts );
			pert.saveTopicWatchList();
			
			return true;
		},
		removeTopic:function( topicId ){
			if (pert.inWatchList(topicId)){
				for ( var i = 0; i < this.topicIds.length; i++ ){
					if ( this.topicIds[ i ] == topicId ){
						this.topicIds.splice( i, 1 );
						this.topicTitles.splice( i, 1 );
						this.numPosts.splice( i, 1 );
						this.postAgeNums.splice( i, 1 );
						this.postAgeUnits.splice( i ,1 );
						this.lastViewNumPosts.splice( i, 1 );
						//console.log()
						pert.saveTopicWatchList();
						
						return true;
					}
				}
			}
			return false;
		},
		updateTopic:function( obj, lastViewNumPosts ){
			if ( lastViewNumPosts == null ){
				lastViewNumPosts = 0;
			}
			if ( pert.inWatchList( obj.details.topicId ) ){
				
				for ( var i = 0; i < this.topicIds.length; i++ ){
					if ( this.topicIds[i] == obj.details.topicId ){
						
						if ( obj != null ){
							//console.log(obj);
							this.numPosts[i] = parseInt( obj.details.numPosts, 10 );
							this.postAgeNums[i] = parseInt( obj.details.postAgeNum, 10 );
							this.postAgeUnits[i] = obj.details.postAgeUnit;
						}
						
						if ( lastViewNumPosts > 0 ){
							this.lastViewNumPosts[i] = lastViewNumPosts;
						}
						
						pert.saveTopicWatchList();
						
						return;
						
					}//if = topicId
				}//for
			}//if inWatchList
		}//updateTopic
	};//pert.topicWatchList
	
	
	pert.saveTopicWatchList = function(){
		//console.log( pert.topicWatchList );
		//
		for ( var v in pert.topicWatchList ){
			
			if ( typeof( pert.topicWatchList[ v ] ) != "function" ){
				eval( "var fn = function(){ GM_setValue( \"bbfch.topicWatchList." + v + "\", pert.topicWatchList[\""+v+"\"].toString() ); }" );
				setTimeout(fn, 1);
			}
		}
		
	};
	/*
	pert.loadTopicWatchList = function(){
		
		//clear all existing details
		pert.topicWatchList.numPosts.splice( 0 );
		pert.topicWatchList.topicIds.splice( 0 );
		pert.topicWatchList.postAgeNums.splice( 0 );
		pert.topicWatchList.postAgeUnits.splice( 0 );
		
		for ( var v in pert.topicWatchList ){
			if (v != "addTopic" && v != "removeTopic" ){
				pert.topicWatchList[v] =  GM_getValue( "bbfch.topicWatchList." + v, "" ).split( "," );
			}
		}
	};*/
	
	pert.anims = {};
	
	pert.flags = {
		sideMenuState: 0,
		sideMenuAnimating: false
	};
	
	pert.sideMenuStyles = {
		width: "14em",
		height: "99.9%",
		padding: "0px",
		margin: "0px",
		position: "absolute",
		zIndex: "1000",
		left: "-13em",
		top: "0px",
		backgroundImage: 'url("' + pert.bottomShadowImage.src + '")',
		backgroundPosition: "0px 100%",
		backgroundRepeat: "repeat-x"
	};
	
	pert.sideMenuBGStyles = {
		width: "95%",
		height: "100%",
		backgroundColor: "#585f69",
		borderBottom: "1px solid #141A25"
	};
	
	pert.sideMenuContainerStyle = {
		width: "98%",
		height: "100%",
		position: "absolute",
		top: "0px",
		left: "0px"
	};
	
	pert.sideMenuButtonStyles = {
		width: "9px",
		height: "62px",
		padding: "0px",
		margin: "0px auto",
		position: "absolute",
		top: "48%",
		right: "4px",
		display: "block",
		backgroundImage: 'url("' + pert.toggleBarButtonImageMed_h.src + '")',
		backgroundPosition: "0px 0px",
		backgroundRepeat: "no-repeat"
	};
	
	pert.config.content = {
		restyleTextArea:true,//if this is set to true, the styles specified in textAreaStyle will be applied
		textAreaStyles: {
			normal: {
				width:"100%",//fill the available area (resizes dynamically when the browser does)
				height: "300px",
				fontSize: "1.2em" //increase the font size by 20%
			}
		},
		toolbarStyles: {
			normal:{
				backgroundColor: "#d4d0c8"
			}
		},
		defaultButtonStyles: {//styles that all buttons will have
			normal:{
				minWidth: "auto",
				height: "auto",
				padding: "0.2em 0.4em 0.4em 0.4em",
				backgroundColor: "#d4d0c8",
				color: "#0c1a44",
				cssFloat: "left",
				cursor: "pointer",
				borderTop: "1px solid #f0f5f7",
				borderLeft: "1px solid #f0f5f7",
				borderBottom: "1px solid #1d3c46",
				borderRight: "1px solid #1d3c46",
				textAlign: "center",
				marginRight: "0.2em"
			},
			hover:{
				borderTop: "1px solid #e0e9ef",
				borderLeft: "1px solid #e0e9ef",
				borderRight: "1px solid #6b818f",
				borderBottom: "1px solid #6b818f",
				backgroundColor: "#C8CFD4",
				color: "#0c3d5f"
			}
		},
		buttons: {
			quote: {
				type:pert.constants.TT_ENCLOSING,
				tag:"quote",
				caption: "[quote]",
				title: "Quote the currently selected text",
				events:{
					selectstart:{
						handler:function(){	return false; }
					}
				}
			},//end quotes
			code: {
				type:pert.constants.TT_ENCLOSING,
				tag:"code",
				caption: "[code]",
				title: "Create a code block.",
				events:{
					selectstart:{
						handler:function(){	return false; }
					}
				}
			},//end code
			codebox: {
				type:pert.constants.TT_ENCLOSING,
				tag:"codebox",
				caption: "[codebox]",
				title: "Create a code box.",
				events:{
					selectstart:{
						handler:function(){	return false; }
					}
				}
			},//end codebox
			anchor: {
				type:pert.constants.TT_ENCLOSING,
				tag:"a",
				caption: "[a]nchor",
				title:"Add a link.",
				attributes:{
					url: {
						name:"url",
						type:"string",
						defaultValue:"http://"
					}
				},
				events:{
					selectstart:{
						handler:function(){	return false; }
					}
				}
			},//end anchor
			bold: {
				type:pert.constants.TT_ENCLOSING,
				tag:"b",
				caption: "[b]old",
				title: "Make the currently selected text bold.",
				styles: {//styles overrides
					normal:{
						fontWeight: "bold"
					}
				},
				events:{
					selectstart:{
						handler:function(){	return false; }
					}
				}
			},//end bold
			italics: {
				type:pert.constants.TT_ENCLOSING,
				tag:"i",
				caption: "[i]talics",
				title: "Make the currently selected text italicized.",
				styles: {//styles overrides
					normal:{
						fontStyle:"italic"
					}
				},
				events:{
					selectstart:{
						handler:function(){	return false; }
					}
				}
			},//end italics
			underline: {
				type:pert.constants.TT_ENCLOSING,
				tag:"u",
				caption: "[u]nderline",
				title: "Make the currently selected text underlined.",
				styles: {//styles overrides
					normal:{
						textDecoration:"underline"
					}
				},
				events:{
					selectstart:{
						handler:function(){	return false; }
					}
				}
			},//end underline
			strikethrough: {
				type:pert.constants.TT_ENCLOSING,
				tag:"s",
				caption: "[s]trikethrough",
				title: "Add a line through the currently selected text.",
				styles: {//styles overrides
					normal:{
						textDecoration:"line-through"
					}
				},
				events:{
					selectstart:{
						handler:function(){	return false; }
					}
				}
			},//end strikethrough
			codearc: {
				type:pert.constants.TT_SELFCLOSING,
				tag:"codearc",
				caption: "[codearc]",
				title:"Add a link to a code archive entry.",
				attributes:{
					id: {
						name:"Code Archive Id",
						type:"integer",
						defaultValue:""
					}
				},
				events:{
					selectstart:{
						handler:function(){	return false; }
					}
				}
			},//end codearc
			faq: {
				type:pert.constants.TT_SELFCLOSING,
				tag:"faq",
				caption: "[faq]",
				title:"Add a link to an FAQ item.",
				attributes:{
					id: {
						name:"FAQ Id",
						type:"integer",
						defaultValue:"2"
					}
				},
				events:{
					selectstart:{
						handler:function(){	return false; }
					}
				}
			}//end faq
			/*customButtonTest: {
				type:constants.TT_ENCLOSING,
				tag:"",
				caption: "custom",
				title: "A custom button",
				events:{
					selectstart:{
						handler:function(){	return false; }
					},
					render:{
						handler:function(){ 
							var container = document.createElement('div');
							container.appendChild( document.createTextNode("Custom Renderer applied") );
							var containerStyles = {
								color: "#000",
								backgroundColor: "#ec8b8b",
								minWidth: "4em",
								height: "1.5em",
								cssFloat: "left",
								padding: "0.1em",
								cursor: "pointer",
								border: "1px solid black"
							};
							applyStyleObjectToElement(containerStyles, container);
							return container;
						}
					},//end render
					click:{
						handler:function(event){
							console.log('clicked');
						}
					}
				}
			}//end custom button*/
		},
		sideMenu: {
			alwaysVisible: true
		}
	};
	
	
	// POST COLLAPSING CONFIGURATION OPTIONS
	pert.config.collapsePosts = {
		collapsePosts: true, //enable or disable post collapsing
		collapsedByDefault: true,//determines whether the posts should be collapsed by default or not
		postsThreshold: 15, //the number of posts that must exist before collapsing will occur
		collapseAfter: 3, //number of posts to leave expanded at the top
		dontCollapseLast: 2 //number of posts to leave expanded at the bottom
	};
	
	pert.config.topicWatch = {
		watchInterval: 60000
	};
	
	/**
	 * Load the configuration
	 * 
	 ********************/
	pert.loadConfig = function(){
		pert.config.content.restyleTextArea = GM_getValue( "bbfch.contentConfig.restyleTextArea", pert.config.content.restyleTextArea );
		for (var v in pert.config.content.defaultButtonStyles.normal){
			pert.config.content.defaultButtonStyles.normal[v] = GM_getValue( "bbfch.config.content.defaultButtonStyles.normal."+v, pert.config.content.defaultButtonStyles.normal[v] );
		}
		for (var v in pert.config.content.textAreaStyles.normal){
			pert.config.content.textAreaStyles.normal[v] = GM_getValue( "bbfch.config.content.textAreaStyles.normal."+v, pert.config.content.textAreaStyles.normal[v] );
		}
		for (var v in pert.config.collapsePosts){
			pert.config.collapsePosts[v] = GM_getValue( "bbfch.config.collapsePosts." + v, pert.config.collapsePosts[v]);
		}
		for (var v in pert.config.content.toolbarStyles.normal){
			pert.config.content.toolbarStyles.normal[v] = GM_getValue( "bbfch.config.content.toolbarStyles.normal." + v, pert.config.content.toolbarStyles.normal[v]);
		}
		pert.toggleImage.src = GM_getValue( "bbfch.toggleImage.src", pert.toggleImage.src);
		pert.jumpLinkImage.src = GM_getValue( "bbfch.jumpLinkImage.src", pert.jumpLinkImage.src);
		pert.toggleBarButtonImage.src = GM_getValue( "bbfch.toggleBarButtonImage.src", pert.toggleBarButtonImage.src);
		pert.toggleBarButtonImageMed.src = GM_getValue( "bbfch.toggleBarButtonImageMed.src", pert.toggleBarButtonImageMed.src);
		pert.toggleBarButtonImageMed_h.src = GM_getValue( "bbfch.toggleBarButtonImageMed_h.src", pert.toggleBarButtonImageMed_h.src);
		pert.config.content.sideMenu.alwaysVisible = GM_getValue( "bbfch.config.content.sideMenu.alwaysVisible", pert.config.content.sideMenu.alwaysVisible);
		
		//pert.topicWatchList
		//get the topic Id's
		for ( var v in pert.topicWatchList ){
			if ( typeof(pert.topicWatchList[v]) != "function" ){
				
				var val = GM_getValue( "bbfch.topicWatchList." + v, "" ).split( "," );
				
				if ( val != "" ){
					if (v != "postAgeUnits" && v != "topicTitles"){
						for ( var i = 0; i < val.length; i++ ){
							val[i] = parseInt(val[i], 10);
						}
					}
					pert.topicWatchList[v] = val;
					
				}
				
			}
		}
		
		for (var v in pert.config.topicWatch ){
			pert.config.topicWatch[v] = GM_getValue( "bbfch.config.topicWatch." + v, pert.config.topicWatch[v] );
		}
		
		//pert.dialogueConfig.styles.minHeight = GM_getValue( "bbfch.config.dialogue.minHeight", pert.dialogueConfig.styles.minHeight );
		pert.dialogueConfig.styles.minWidth = GM_getValue( "bbfch.config.dialogue.minWidth", pert.dialogueConfig.styles.minWidth );
		//pert.dialogueConfig.styles.width = GM_getValue( "bbfch.config.dialogue.width", pert.dialogueConfig.styles.width );
		//pert.dialogueConfig.styles.height = GM_getValue( "bbfch.config.dialogue.height", pert.dialogueConfig.styles.height );
		pert.dialogueConfig.styles.backgroundColor = GM_getValue( "bbfch.config.dialogue.backgroundColor", pert.dialogueConfig.styles.backgroundColor );
		pert.dialogueConfig.styles.borderBottom = GM_getValue( "bbfch.config.dialogue.borderBottom", pert.dialogueConfig.styles.borderBottom );
		pert.dialogueConfig.styles.padding = GM_getValue( "bbfch.config.dialogue.padding", pert.dialogueConfig.styles.padding );
		/*
		styles: {
			width: "50%",
			height: "20%",
			minWidth: "50%",
			minHeight: "20%",
			opacity: "0.0",
			backgroundColor: "#585f69",
			borderBottom: "1px solid #141A25",
			padding: "1em",
			position: "absolute",
			top: document.body.scrollTop + (document.body.clientHeight * 0.4),
			left: "25%",
			},
			timeout: 5000
		}
		*/
	
		//pert.topicWatchList.topicIds = GM_getValue("bbfch.topicWatchList.topicIds", "").split(",");
		
		//
		
	};
	
	/**
	 * Save the configuration
	 * 
	 ********************/
	pert.saveConfig = function(){
		GM_setValue( "bbfch.config.content.restyleTextArea", pert.config.content.restyleTextArea );
		
		for (var v in pert.config.content.defaultButtonStyles.normal){
			GM_setValue( "bbfch.config.content.defaultButtonStyles.normal."+v, pert.config.content.defaultButtonStyles.normal[v] );
		}
		for (var v in pert.config.content.textAreaStyles.normal){
			GM_setValue( "bbfch.config.content.textAreaStyles.normal."+v, pert.config.content.textAreaStyles.normal[v] );
		}
		for (var v in pert.config.collapsePosts){
			GM_setValue( "bbfch.config.collapsePosts." + v, pert.config.collapsePosts[v]);
		}
		for (var v in pert.config.content.toolbarStyles.normal){
			GM_setValue( "bbfch.config.content.toolbarStyles.normal." + v, pert.config.content.toolbarStyles.normal[v]);
		}
		GM_setValue( "bbfch.toggleImage.src", pert.toggleImage.src);
		GM_setValue( "bbfch.jumpLinkImage.src", pert.jumpLinkImage.src);
		GM_setValue( "bbfch.toggleBarButtonImage.src", pert.toggleBarButtonImage.src);
		GM_setValue( "bbfch.toggleBarButtonImageMed.src", pert.toggleBarButtonImageMed.src);
		GM_setValue( "bbfch.toggleBarButtonImageMed_h.src", pert.toggleBarButtonImageMed_h.src);
		GM_setValue( "bbfch.config.content.sideMenu.alwaysVisible", pert.config.content.sideMenu.alwaysVisible);

		for ( var v in pert.topicWatchList ){
			if ( typeof( pert.topicWatchList[v] ) != "function"){
				//console.log( v );
				GM_setValue( "bbfch.topicWatchList." + v, pert.topicWatchList[v].join( "," ) );
			}
		}
		
		for (var v in pert.config.topicWatch ){
			GM_setValue( "bbfch.config.topicWatch." + v, pert.config.topicWatch[v] );
		}
		
		//GM_setValue( "bbfch.config.dialogue.minHeight", pert.dialogueConfig.styles.minHeight );
		GM_setValue( "bbfch.config.dialogue.minWidth", pert.dialogueConfig.styles.minWidth );
		GM_setValue( "bbfch.config.dialogue.backgroundColor", pert.dialogueConfig.styles.backgroundColor );
		GM_setValue( "bbfch.config.dialogue.borderBottom", pert.dialogueConfig.styles.borderBottom );
		GM_setValue( "bbfch.config.dialogue.padding", pert.dialogueConfig.styles.padding );
		
		GM_setValue( "bbfch.config.saved", true );
	};
	
	/**
	 * make the toolbar element and position it below the textarea
	 ********************/
	pert.makeToolbar = function(){
		if (window.location.pathname.substring(0,5).toLowerCase() == "/home"){
			return;
		}
		//ADD FORUM CODES BUTTONS
		//since the textarea has no unique identifier, we need to get it in a less efficient way
		var contentAreas = document.evaluate( "//textarea[@name='content']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
		//pert.contentArea = {};
		var contentConfig = pert.config.content;
		var collapsePostsConfig = pert.config.collapsePosts;
		
		if ( contentAreas.snapshotLength == 1 ){
			pert.contentArea = contentAreas.snapshotItem(0);
			
			//create the container for the helper buttons
			pert.toolbar = document.createElement("div");
				pert.toolbar.id = "bbfch_toolbar";
				applyStyleObjectToElement(contentConfig.toolbarStyles.normal, pert.toolbar);
			
			if ( contentConfig.restyleTextArea === true ){
				applyStyleObjectToElement(contentConfig.textAreaStyles.normal, pert.contentArea);
			}
			//add the buttons
			if ( contentConfig.buttons ){
				for ( var b in contentConfig.buttons ){
					if ( typeof(contentConfig.buttons[b].events.render) != "undefined" ){
						var customButton = contentConfig.buttons[b].events.render.handler( contentConfig.buttons[b], b );
						
							attachEventsToElement(contentConfig.buttons[b].events, customButton, b);
							
							toolbar.appendChild(customButton);
					} else {
						
						var newButton = createButton( contentConfig.buttons[b], b );
						
						if ( contentConfig.buttons[b].title ){ newButton.title = contentConfig.buttons[b].title; }
						
						applyStyleObjectToElement( contentConfig.defaultButtonStyles.normal, newButton );
						
						if ( contentConfig.buttons[b].styles && contentConfig.buttons[b].styles.normal ){
							applyStyleObjectToElement( contentConfig.buttons[b].styles.normal, newButton );
						}
						if ( contentConfig.buttons[b].preventDefaultClick !== true ){
							//newButton.addEventListener('click', defaultClickHandler);
							eval("function click_" + b + "(){ defaultClickHandler.call( contentConfig.buttons[\"" + b + "\"] ); }");
							newButton.addEventListener('click', eval("click_"+b), false);
						}
						newButton.addEventListener('mouseover', function(e){
							applyStyleObjectToElement(pert.config.content.defaultButtonStyles.hover, this);
						}, false);
						newButton.addEventListener('mouseout', function(e){
							applyStyleObjectToElement(pert.config.content.defaultButtonStyles.normal, this);
						}, false);
						
						contentConfig.buttons[b].element = newButton;
						pert.toolbar.appendChild(newButton);
					}
						
				}
			}
			//insert a clearing element afterwards
			var clearing = document.createElement( "div" );
				clearing.style.clear = "both";
				pert.toolbar.appendChild( clearing );
				
			insertAfter( pert.toolbar, pert.contentArea );
			
		} else {
			//console.log('Cannot find content textarea.');
		}
		
	};
	
	/**
	 * add the collapsible posts
	 * 
	 ********************/
	pert.collapsePosts = function(){
		if (window.location.pathname.substring(0,5).toLowerCase() == "/home"){
			return;
		}
		
		var contentConfig = pert.config.content;
		var collapsePostsConfig = pert.config.collapsePosts;
		//COLLAPSE POSTS
		if ( collapsePostsConfig.collapsePosts === true ){
			var allPosts = document.evaluate( "//td[@class='posttext']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
			var allPostHeads = document.evaluate( "//td[@class='posthead']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
			
			if ( allPosts.snapshotLength > collapsePostsConfig.collapseAfter ){
				
				//loop through all posts and collapse them, then add toggle link
				for ( var p = 0; p < allPosts.snapshotLength; p++ ){
					var post = allPosts.snapshotItem(p);
						
						var postContainer = document.createElement("span");
							postContainer.id = "bbfch_post_" + p;
							postContainer.className = "bbfch_post";
							
							while ( post.firstChild ){
								
								postContainer.appendChild(post.firstChild);
								
							}
							
						post.appendChild( postContainer );
						/*console.log(p);
						console.log(collapsePostsConfig.collapseAfter);
						console.log(collapsePostsConfig.dontCollapseLast);
						*/
						//if ( ( p > collapsePostsConfig.collapseAfter) && ( p < collapsePostsConfig.dontCollapseLast ) ){
							if (
								
								collapsePostsConfig.collapsedByDefault 
								&& p > ( collapsePostsConfig.collapseAfter - 1 ) 
								&& p < ( allPosts.snapshotLength - collapsePostsConfig.dontCollapseLast )
								&& allPosts.snapshotLength > collapsePostsConfig.postsThreshold
								
							){
								postContainer.style.display = "none";
								
							} else {
								
								postContainer.style.display = "block";
								
							}
						//}
						
					var postHead = allPostHeads.snapshotItem(p);
					
					var phTarget = postHead.firstChild.firstChild.firstChild.firstChild;
					var userLink = postHead.firstChild.firstChild.firstChild.firstChild.firstChild;
						userLink.style.cssFloat = "left";
						//console.log(phTarget);
						var toggleLink = document.createElement("a");
							toggleLink.href="#togglePost";
							toggleLink.id = "bbfch_post_" + p + "_toggleLink";
							
							var toggleLinkStyles = {
								backgroundImage: "url(\"" + pert.toggleImage.src + "\")",
								backgroundRepeat: "no-repeat",
								backgroundPosition: "50% 0px",
								width: "16px",
								height: "16px",
								display: "block",
								cssFloat: "left",
								marginRight: "3px"
							}
							
							applyStyleObjectToElement( toggleLinkStyles, toggleLink );
							
							var clickFunc = eval("function(event){toggleLinkClick.call( document.getElementById(\"bbfch_post_" + p + "\"), event ); };");
							
							toggleLink.addEventListener("click", clickFunc, false);
							
							if ( postContainer.style.display == "none" ){
								toggleLink.style.backgroundPosition = "50% 0px";
							} else {
								toggleLink.style.backgroundPosition = "50% -16px";
							}
					phTarget.insertBefore(toggleLink, userLink);
				}//end for
				
				var main = document.evaluate( "//div[@class='main']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
				var main = main.snapshotItem(0);
				var jumpLink = document.createElement("a");
					var jumpLinkStyle = {
						minWidth: "16px",
						minHeight: "16px",
						backgroundImage : "url(\"" + pert.jumpLinkImage.src + "\")",
						backgroundRepeat: "no-repeat",
						backgroundPosition: "0px 0px",
						paddingLeft: "16px",
						paddingRight: "4px",
						cssFloat:"right",
						display:"block"
					}
					applyStyleObjectToElement(jumpLinkStyle, jumpLink);
					jumpLink.appendChild( document.createTextNode("Jump to Bottom") );
					jumpLink.href = "#bbfch_toolbar";
				main.insertBefore(jumpLink, main.firstChild);
					
				var expandAllContainer = document.createElement('span');
					//expandAllContainer.style.cssFloat = "right";
				var expandAll = document.createElement("a");
					expandAll.id = "bbfch_show_all";
					expandAll.href = "#ExpandAll";
					var expandAllImage = document.createElement("span");
						var expandAllImageStyles = {
							cssFloat: "left",
							width: "16px",
							height: "16px",
							backgroundImage: "url(\"" + pert.toggleImage.src + "\")",
							backgroundRepeat: "no-repeat",
							backgroundPosition: "0px 0px",
						}
					applyStyleObjectToElement(expandAllImageStyles, expandAllImage);
					var expandAllStyle = {
						cssFloat: "right",
						marginRight: "3px"
					}
					applyStyleObjectToElement( expandAllStyle, expandAll );
					
					expandAll.appendChild( expandAllImage );
					expandAll.appendChild( document.createTextNode("Expand All") );
					expandAll.addEventListener( "click", function(event){ toggleAllPosts.call({source:this, toggleType:"expand"}, event) }, false );
					
				var expandAllCopy = expandAll.cloneNode(true);
					expandAllCopy.addEventListener( "click", function(event){ toggleAllPosts.call({source:this, toggleType:"expand"}, event) }, false );
				expandAllContainer.appendChild( expandAll );
				
				var collapseAllContainer = document.createElement('span');
					//collapseAllContainer.style.cssFloat = "right";
				var collapseAll = document.createElement("a");
					collapseAll.id = "bbfch_show_all";
					collapseAll.href = "#CollapseAll";
					var collapseAllImage = document.createElement("span");
						var collapseAllImageStyles = {
							cssFloat: "left",
							width: "16px",
							height: "16px",
							backgroundImage: "url(\"" + pert.toggleImage.src + "\")",
							backgroundRepeat: "no-repeat",
							backgroundPosition: "0px -16px"
						}
					applyStyleObjectToElement( collapseAllImageStyles, collapseAllImage );
						
					collapseAll.style.cssFloat = "right";
					collapseAll.appendChild(collapseAllImage);
					/*
						collapseAll.style.cssFloat = "right";
						collapseAll.style.backgroundImage = "url(\"" + toggleImage.src + "\")";
						collapseAll.style.backgroundRepeat = "no-repeat";
						collapseAll.style.backgroundPosition = "0px -16px";
						collapseAll.style.paddingLeft = "16px";
						*/
					collapseAll.appendChild( document.createTextNode("Collapse All") );
					collapseAll.addEventListener("click", function(event){ toggleAllPosts.call({source:this, toggleType:"collapse"}, event) }, false);
				var collapseAllCopy = collapseAll.cloneNode(true);
					collapseAllCopy.addEventListener("click", function(event){ toggleAllPosts.call({source:this, toggleType:"collapse"}, event) }, false);
					
					collapseAllContainer.appendChild( collapseAll );
					
				main.insertBefore(expandAllContainer, main.firstChild);
				main.insertBefore(collapseAllContainer, main.firstChild);
				//main.insertBefore(collapseAll, main.firstChild);
				
				main.insertBefore(collapseAllCopy, pert.contentArea.parentNode);
				main.insertBefore(expandAllCopy, pert.contentArea.parentNode);
			}
			
		}
	};//end collapsePosts
	
	/**
	 * Add the top Menu (now the sidebar)
	 * 
	 ********************/
	pert.addSideMenu = function(){
		
		var Event = YAHOO.util.Event;
		var Dom = YAHOO.util.Dom;
		
		pert.sideMenu = document.createElement("div");
			pert.sideMenu.id = "bbfch_sideMenu";
			
			var sideMenuStyles = pert.sideMenuStyles;

		var sideMenuBG = document.createElement("div");//add the background as an element so that the opacity doesn't get applied to the top menu's children
			sideMenuBG.id = "bbfch_sideMenuBG";
			var sideMenuBGStyle = pert.sideMenuBGStyles;

		pert.sideMenuContainer = document.createElement("div");
			pert.sideMenuContainer.id = "bbcfh_sideMenuContainer";
			var sideMenuContainerStyle = pert.sideMenuContainerStyle;

		applyStyleObjectToElement( sideMenuBGStyle, sideMenuBG );
		applyStyleObjectToElement(sideMenuContainerStyle, pert.sideMenuContainer);
		Dom.setStyle(sideMenuBG, "opacity", 0.9);
		
		applyStyleObjectToElement( sideMenuStyles, pert.sideMenu );
		
		pert.sideMenu.appendChild(sideMenuBG);
		pert.sideMenu.appendChild(pert.sideMenuContainer);
		var sideMenuButton = document.createElement("a");
			sideMenuButton.id = "bbfch_sideMenuButton";
			var sideMenuButtonStyles = pert.sideMenuButtonStyles;

		pert.anims.sideMenuSlideOut = new YAHOO.util.Anim(pert.sideMenu, { left: { to: 0, unit: "em" } }, 0.5, YAHOO.util.Easing.easeOutStrong);
			pert.anims.sideMenuSlideOut.onStart.subscribe(function(){
				pert.flags.sideMenuAnimating = true;
			});
			pert.anims.sideMenuSlideOut.onTween.subscribe(function(){
				var Dom = YAHOO.util.Dom;
				var bg = Dom.get('bbfch_sideMenuBG');
				var op = (pert.anims.sideMenuSlideOut.currentFrame / pert.anims.sideMenuSlideOut.totalFrames) * 0.9;
					Dom.setStyle(bg, "opacity", op);
			});
			pert.anims.sideMenuSlideOut.onComplete.subscribe(function(){
				pert.flags.sideMenuAnimating = false;
				pert.flags.sideMenuState = 1;
				var Dom = YAHOO.util.Dom;
				var button = Dom.get("bbfch_sideMenuButton");
					Dom.setStyle( button, "background-position", "-9px 0px" );
			});
		pert.anims.sideMenuSlideIn = new YAHOO.util.Anim(pert.sideMenu, { left: { to: -13, unit: "em" } }, 0.5, YAHOO.util.Easing.easeInStrong);
			pert.anims.sideMenuSlideIn.onStart.subscribe(function(){
				pert.flags.sideMenuAnimating = true;
			});
			pert.anims.sideMenuSlideIn.onTween.subscribe(function(){
				var Dom = YAHOO.util.Dom;
				var bg = Dom.get('bbfch_sideMenuBG');
				var op =  1 - ((pert.anims.sideMenuSlideIn.currentFrame / pert.anims.sideMenuSlideIn.totalFrames)* 0.9); 
					Dom.setStyle(bg, "opacity", op );
			});
			pert.anims.sideMenuSlideIn.onComplete.subscribe(function(){
				pert.flags.sideMenuAnimating = false;
				pert.flags.sideMenuState = 0;
				var Dom = YAHOO.util.Dom;
				var button = Dom.get("bbfch_sideMenuButton");
				Dom.setStyle(button, "background-position", "0px 0px");
			});
		
		applyStyleObjectToElement( sideMenuButtonStyles, sideMenuButton );
		sideMenuButton.href = "#";
		var sideMenuButtonClick = function(e){
			if (pert.flags.sideMenuAnimating){
				return;
			}
			switch(pert.flags.sideMenuState){
				case 0:
					pert.anims.sideMenuSlideOut.animate();
				break;
				case 1:
					pert.anims.sideMenuSlideIn.animate();
				break;
			}
			
			YAHOO.util.Event.stopEvent(e);
			Event.preventDefault(e);
			
		};
		Event.addListener( sideMenuButton, "click", sideMenuButtonClick );
		
		//Event.addListener( pert.sideMenu, "mouseout", sideMenuButtonClick );
		pert.sideMenu.appendChild( sideMenuButton );
		document.body.appendChild( pert.sideMenu );
		
		if ( pert.config.content.sideMenu.alwaysVisible === true ){
			function scrollListener(e){
				var Dom = YAHOO.util.Dom;
				Dom.setStyle(pert.sideMenu, "top", document.body.scrollTop+"px");
				//console.log("scrolled");
			}
			YAHOO.util.Event.addListener( window, "scroll", scrollListener, null );
		}
	};
	
	/**
	 * add the watch thread button to the sidebar
	 * 
	 ********************/
	pert.addWatchThreadButton = function(){
		var Event = YAHOO.util.Event;
		var button = new YAHOO.widget.Button({
			id: "btnWatchThread",
			type: "button",
			label: "Watch this thread",
			container: pert.sideMenuContainer
		});
		
		var btnEl = YAHOO.util.Dom.get("btnWatchThread");
		var input = btnEl.firstChild.firstChild;
		
		var btnStyle = {
			backgroundColor: "#c0c0c0",
			color: "#868f9b",
			display: "block",
			width: input.scrollWidth + "px",
			border: "1px solid black",
			margin: "10px"
		};
		applyStyleObjectToElement(btnStyle, btnEl);
		
		Event.addListener( input, "click", function(e){
			pert.watchTopic( parseInt( gup("topic"), 10 ) );
		} );
		
	};
	/**
	 * add the unwatch thread button to the sidebar
	 * 
	 ********************/
	pert.addUnwatchThreadButton = function(){
		var Event = YAHOO.util.Event;
		var button = new YAHOO.widget.Button({
			id: "btnUnWatchThread",
			type: "button",
			label: "Un-watch this thread",
			container: pert.sideMenuContainer
		});
		
		var btnEl = YAHOO.util.Dom.get("btnUnWatchThread");
		var input = btnEl.firstChild.firstChild;
		
		var btnStyle = {
			backgroundColor: "#c0c0c0",
			color: "#868f9b",
			display: "block",
			width: input.scrollWidth + "px",
			border: "1px solid black",
			margin: "10px"
		};
		applyStyleObjectToElement(btnStyle, btnEl);
		
		Event.addListener( input, "click", function(e){
			//pert.watchTopic( parseInt( gup("topic"), 10 ) );
			pert.topicWatchList.removeTopic( parseInt( gup( "topic" ), 10 ) );
			pert.updateWatchLinks();
		} );
		
	};
	
	pert.inWatchList = function(topicId){
		for ( var i = 0; i < pert.topicWatchList.topicIds.length; i++ ){
			if ( pert.topicWatchList.topicIds[i] == topicId ){
				return true;
			}
		}
		return false;
	}

	
	/**
	 * add the specified topic id to the watchlist
	 * 
	 * @param integer topicId
	 ********************/
	pert.watchTopic = function( topicId ){
		
		if ( typeof( topicId ) == "number" ){

			if (pert.inWatchList(topicId)){
				//console.log("topic exists already");
					var br = document.createElement("br");
				var msg = document.createElement("span");
					var msgTitle = document.createElement("strong");
						msgTitle.appendChild( document.createTextNode("Cannot add topic to watch list") );
					msg.appendChild( msgTitle );
				msg.appendChild( br.cloneNode( false ) );
				msg.appendChild( br.cloneNode( false ) );
				msg.appendChild( document.createTextNode( "Topic is already in the watch list" ) );
				
				pert.message( msg )
				return;
			}
			
			var callBackObject = {
				callback:{
					success:function( result ){
						
						//console.log( "in success" );
						//console.log( result );
						pert.topicWatchList.addTopic( result );
						pert.updateWatchLinks();
						var br = document.createElement("br");
						var msg = document.createElement( "span" );
							var strong = document.createElement( "strong" );
								strong.appendChild( document.createTextNode( "Watch Topic" ) );
							
							msg.appendChild( strong );
							msg.appendChild( br.cloneNode( false ) );
							msg.appendChild( br.cloneNode( false ) );
							msg.appendChild( document.createTextNode( "Topic Watch activated for topic id: " + result.details.topicId  ) );
						pert.message( msg );
						
					},
					failure:function( result ){
						
						var br = document.createElement("br");
						var msg = document.createElement( "span" );
							var strong = document.createElement( "strong" );
								strong.appendChild( document.createTextNode( "Watch Topic" ) );
								strong.appendChild( br.cloneNode( false ) );
								strong.appendChild( br.cloneNode( false ) );
								
							msg.appendChild( strong );
							msg.appendChild( document.createTextNode( "Topic Watch was NOT activated for topic id: " + result.topicId ) );
							msg.appendChild( document.createElement( br.cloneNode( false ) ) );
							msg.appendChild( document.createTextNode( "Could not retrieve topic details." ) );
						pert.message( msg );
						
					}
				}
			};
			
			pert.getTopicDetails( topicId, callBackObject );
			
		}
		
	};
	
	
	/**
	 * @param number topicId
	 * @param object topicDetails
	 ******************************************/
	pert.getTopicDetails = function( topicId, callBackObject ){
		var requestDetails = {
			method: "GET",
			url: "http://" + window.location.hostname + "/Community/posts.php?topic=" + topicId,
			headers: {
				'User-Agent': Navigator.userAgent + " (Greasemonkey)",
				'Accept': 'text/html, text/json, application/json, application/xml, text/xml'
			},
			data: null,
			callback: {
				success: function( response ){
					var tags = new RegExp("(<td class=\"posthead\">)", "gm");
					var responseText = response.responseText;
						responseText = responseText.replace(/\n/, "");
						responseText = responseText.replace(/\r/, "");
						
					var titles = responseText.match( /<title\s>(.*?)<\/title>/gm );
						var title = titles[0].match( /<title\s>(.*?)<\/title>/ )[1];
					
					var postheads = responseText.match( /(<td class=\"posthead\">)/gm );
					
						var postAnchors = responseText.match( /(<a name=\"[0-9]*\">)/gm );
						var postDates = responseText.match( /<font class=tiny>[(]Posted (.*) ago[)]<\/font>/gm );
						var postAge = postDates[postheads.length - 1].match( /<font class=tiny>[(]Posted (.*) ago[)]<\/font>/ )[1].match(/([0-9]*?) (\w*)/);
						var result = {
							updated : true,
							details : {
								topicId: topicId,
								topicTitle: title,
								numPosts: parseInt( postheads.length, 10 ),
								postId: parseInt( postAnchors[postheads.length - 1].match( /<a name=\"([0-9]*)\">/ )[1], 10 ),
								postAgeNum: parseInt( postAge[1], 10 ),
								postAgeUnit: postAge[2]
							}
						}
						//console.log( "got result" );
						callBackObject.callback.success( result );
				},
				failure: function( response ){
					console.log( response );
				}
			},
			failure: callBackObject.callback.failure
		}//requestDetails
		
		var transaction = YAHOO.util.Connect.asyncRequest( requestDetails.method, requestDetails.url, requestDetails.callback, requestDetails.data );
		
	}
	
	
	/**
	 * Display a popup message to the user
	 * 
	 * @param mixed msg
	 ******************************/
	pert.message = function( msg, autoClose, dialogueType, dlgCallbacks ){
		switch( typeof( msg ) ){
			case "string":
			case "number":
				var newNode = document.createElement( 'strong' );
					newNode.appendChild( document.createTextNode( msg ) );
			break;
			case "object":
				if ( msg.tagName != "" ){//if it's a DOM element
					newNode = msg;
				}
			break;
			default:
				console.log("Unsupported message type: "+typeof(msg)+" val: "+msg);
				return;
			break;
		}
		pert.createDialogue( newNode, autoClose, dialogueType, dlgCallbacks );
		//console.log( msg.constructor.name );
		//console.log( msg );
	};
	
	/**
	 * @param nsIDOMNode contentNode - the content of the dialogue
	 * @param boolean autoClose - should the dialogue close itself?
	 * @param number dialogueType - should be one of the db constants
	 * @param object dlgCallbacks - should contain a callback function for each of the button types 
	 */
	pert.createDialogue = function cd( contentNode, autoClose, dialogueType, dlgCallbacks ){
		if (dialogueType == null){
			dialogueType = pert.constants.dbOK;
		}
		if (autoClose == null){
			autoClose = true;
		}
		
		
		var Dom = YAHOO.util.Dom;
		var Event = YAHOO.util.Event;
		
		if ( pert.dialogue != null ) {
			var target = Dom.get("dialogue_content");
			target.appendChild( document.createElement( "br" ) );
			target.appendChild( contentNode );
			return;
		}
		
		var main = document.evaluate( "//div[@class='main']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
		var main = main.snapshotItem(0);
		pert.dialogueTarget = main;
		

		pert.dialogue = document.createElement( 'div' );
		var content = document.createElement( 'div' );
			content.id = "dialogue_content";
			content.appendChild( contentNode );
		pert.dialogue.appendChild( content );
		
		var dlgStyle = {
			top: document.body.scrollTop + (document.body.clientHeight * 0.4)
		}
		
		applyStyleObjectToElement( pert.dialogueConfig.styles, pert.dialogue );
		applyStyleObjectToElement( dlgStyle, pert.dialogue );
		
		
		pert.dialogueTarget.appendChild( pert.dialogue );
		
		//add buttons
		
		pert.dialogue.appendChild( document.createElement( "hr" ) );
		var btnContainer = document.createElement("div");
		var containerStyles = {
			textAlign: "center",
			height: "2em"
		};
		
		applyStyleObjectToElement( containerStyles, btnContainer );
		var OKListener = function(){
			pert.dialogueOutAnim.animate();
			//console.log("clicked");
		};
		
		
		switch( dialogueType ){
			case pert.constants.dbOK://only one supported for now
			
				var btnOK = document.createElement("input");
					btnOK.type = "button";
					btnOK.name = "dialogue_btn_OK";
					btnOK.id = "dialogue_btn_OK";
					btnOK.value = "OK";
				if ( typeof( dlgCallbacks ) != "undefined" && dlgCallback.OKClick ){
					Event.addListener( "click", btnOK, dlgCallbacks.OKClick, {result:"ok"} );
				}
				Event.addListener( btnOK, "click", OKListener );
				btnContainer.appendChild( btnOK );
			break;
			
			case pert.constants.dbOKCancel:
			
				var btnOK = document.createElement("input");
					btnOK.type = "button";
					btnOK.name = "dialogue_btn_OK";
					btnOK.id = "dialogue_btn_OK";
					btnOK.value = "OK";
				
				if ( typeof( dlgCallbacks ) != "undefined" && dlgCallback.OKClick ){
					Event.addListener( "click", btnOK, dlgCallbacks.OKClick, {result:"ok"} );
				}
				Event.addListener( btnOK, "click", OKListener );
				btnContainer.appendChild( btnOK );
				
				btnContainer.appendChild( document.createTextNode(" ") );

				var btnCancel = document.createElement("input");
					btnCancel.type = "button";
					btnCancel.name = "dialogue_btn_OK";
					btnCancel.id = "dialogue_btn_OK";
					btnCancel.value = "OK";
				
				if ( typeof( dlgCallbacks ) != "undefined" && dlgCallback.cancelClick  ){
					Event.addListener( btnCancel, "click", dlgCallbacks.CancelClick, {result:"cancel"} );
				}
				
				btnContainer.appendChild( btnCancel );
				
			break;
		}
		
		pert.dialogue.appendChild( btnContainer );
		
		if ( autoClose ){
			pert.dialogueInAnim = new YAHOO.util.Anim(pert.dialogue, { opacity: { to: 0.9 } }, 0.5, YAHOO.util.Easing.easeInStrong);
				pert.dialogueInAnim.onComplete.subscribe( function(){
					
					window.setTimeout(function(){ 
						if (pert.dialogue != null){
							pert.dialogueOutAnim.animate();
						}
					}, pert.dialogueConfig.timeout);
				});
		} else {
			pert.dialogueInAnim = new YAHOO.util.Anim(pert.dialogue, { opacity: { to: 0.9 } }, 0.5, YAHOO.util.Easing.easeInStrong);
		}
		
		pert.dialogueOutAnim = new YAHOO.util.Anim(pert.dialogue, { opacity: { to: 0 } }, 0.5, YAHOO.util.Easing.easeOutStrong);
			pert.dialogueOutAnim.onComplete.subscribe( function(){
				pert.dialogueTarget.removeChild( pert.dialogue );
				pert.dialogue = null;
			});
		
			function scrollListener(e){
				var Dom = YAHOO.util.Dom;
				Dom.setStyle( pert.dialogue, "top", document.body.scrollTop + (document.body.clientHeight * 0.4) + "px" );
				//console.log("scrolled");
			}
			YAHOO.util.Event.addListener( window, "scroll", scrollListener, null );
			
		pert.dialogueInAnim.animate();
		
	};
	
	/**
	 * deprecated
	 ********************/
	pert.unwatchTopic = function( topicId ){
		console.log( "Unwatch request for: " + topicId );
		
		
	};
	
	/**
	 * 
	 ********************/
	pert.countPostsInMarkup = function( markup ){
		return markup.match( /(<td class=\"posthead\">)/gm ).length;
	};
	
	/**
	 * 
	 * returns true if the topic post count is different
	 * @param number topicId
	 * @param number previousPostCount
	 ******************************************************/
	pert.checkTopic = function( topicId, previousPostcount, resultCallback ){
		
		

		var requestDetails = {
			method: "GET",
			url: "http://" + window.location.hostname + "/Community/posts.php?topic="+topicId,
			headers: {
				'User-Agent': Navigator.userAgent + " (Greasemonkey)",
				'Accept': 'text/html, text/json, application/json, application/xml, text/xml'
			},
			data: null,
			callback: {
				success: function( response ){
					var tags = new RegExp("(<td class=\"posthead\">)", "gm");
					var responseText = response.responseText;
						responseText = responseText.replace(/\n/, "");
						responseText = responseText.replace(/\r/, "");
						
					var titles = responseText.match( /<title\s>(.*?)<\/title>/gm );
						var title = titles[0].match( /<title\s>(.*?)<\/title>/ )[1];
					
					var postheads = responseText.match( /(<td class=\"posthead\">)/gm );
					var postAnchors = responseText.match( /(<a name=\"[0-9]*\">)/gm );
					var postDates = responseText.match( /<font class=tiny>[(]Posted (.*) ago[)]<\/font>/gm );
					var postAge = postDates[postheads.length - 1].match( /<font class=tiny>[(]Posted (.*) ago[)]<\/font>/ )[1].match(/([0-9]*?) (\w*)/);
						
					if ( postheads.length > previousPostcount ){

						var result = {
							updated: true,
							success:true,
							details: {
								numPosts: postheads.length,
								postId: postAnchors[postheads.length - 1].match( /<a name=\"([0-9]*)\">/ )[1],
								postAgeNum: postAge[1],
								postAgeUnit: postAge[2]
							}
						};
						//console.log( result );
					} else {
						var result = {
							updated:false,
							success:true,
							details: {
								numPosts: postheads.length,
								postId: postAnchors[postheads.length - 1].match( /<a name=\"([0-9]*)\">/ )[1],
								postAgeNum: postAge[1],
								postAgeUnit: postAge[2]
							}
						};
						//console.log( result );
						
					}
					//console.log( result );
					resultCallback( result );
				},
				failure: function( response ){
					//console.log( response );
					resultCallback( {update:false, success:false} );
				}
			}
		}//requestDetails
		//console.log( "request URL:" + requestDetails.url );
		var transaction = YAHOO.util.Connect.asyncRequest( requestDetails.method, requestDetails.url, requestDetails.callback, requestDetails.data );
				
	};//pert.checkTopic
	
	pert.checkTopics = function(){
		for ( var i = 0; i < pert.topicWatchList.topicIds.length; i++ ){
			
			var callback = eval("function( response ){" +
				"if ( response.updated == true ){" +
				//"	console.log('updated');" +
				"	var msg = document.createElement(\"span\");" +
				"		msg.appendChild( document.createTextNode(\"Topic updated: \") );" +
				"		var a = document.createElement(\"a\");" +
				"			a.href=\"http://" + window.location.hostname + "/Community/posts.php?topic=" + pert.topicWatchList.topicIds[i] + "\";" +
				"			a.appendChild( document.createTextNode(\"" + pert.topicWatchList.topicTitles[i]+ "\") );" +
				"		msg.appendChild(a);" +
				"	pert.message(msg);" +
				"	pert.updateWatchLinks();" +
				"	pert.anims.sideMenuSlideOut.animate();" +
				"	response.details.topicId = " + pert.topicWatchList.topicIds[i] + ";" + 
				"	pert.topicWatchList.updateTopic( response, " + pert.topicWatchList.lastViewNumPosts[i] + " );" +
				"} else {" +
				"	response.details.topicId = " + pert.topicWatchList.topicIds[i] + ";" + 
				"	var lvnp = 0;" +
				"	if ( gup('topic') ){" +
				"		lvnp = response.details.numPosts" +
				"	}" +
				"	pert.topicWatchList.updateTopic( response, lvnp );" +
				"}" +
				"pert.updateWatchLinks(); " +
			"};" );
			pert.checkTopic( pert.topicWatchList.topicIds[i], pert.topicWatchList.numPosts[i], callback );
			
		}
		pert.setLastCheckTime();
	};
	
	/**
	 * 
	 */
	pert.updateWatchLinks = function(){
		clearNodes("bbfch_watchLinkContainer");
		var a = document.createElement("a");
		var br = document.createElement("br");
		
		for ( var i = 0; i < pert.topicWatchList.topicIds.length; i++ ){
			
			var link = a.cloneNode(false);
				link.href = "http://"+window.location.hostname + "/Community/posts.php?topic=" + pert.topicWatchList.topicIds[i];
				link.appendChild( document.createTextNode( pert.topicWatchList.topicTitles[i] ) );
				
				link.title = "Last updated: " + pert.topicWatchList.postAgeNums[i] + " " + pert.topicWatchList.postAgeUnits[i] + " ago.";
				var normalLinkStyle = {
					width: "90%",
					display: "block",
					fontSize: "0.8em"
				};
				
				var updatedLinkStyle = {
					width: "90%",
					display: "block",
					fontSize: "0.8em",
					color: "#f00"
				};
				
				if ( pert.topicWatchList.lastViewNumPosts[i] != pert.topicWatchList.numPosts[i] ){
					applyStyleObjectToElement( updatedLinkStyle, link );
				} else {
					applyStyleObjectToElement( normalLinkStyle, link );
				}
				
			pert.watchLinkContainer.appendChild( link );
			pert.watchLinkContainer.appendChild( br.cloneNode( false ) );
		}
		
		//pert.sideMenuContainer.appendChild( pert.watchLinkContainer );
	};
	
	/**
	 * 
	 */
	pert.createWatchLinks = function(){
		pert.watchLinkContainer = document.createElement("div");
			pert.watchLinkContainer.id = "bbfch_watchLinkContainer";
			var styleObj = {
				width: "85%",
				border: "1px solid #B3C0CF",
				borderBottom: "1px solid #3E4247",
				borderRight: "1px solid #3E4247",
				backgroundColor: "#686F78",
				padding: "0.5em"
			};
		applyStyleObjectToElement( styleObj, pert.watchLinkContainer );
		
		pert.updateWatchLinks();
		pert.sideMenuContainer.appendChild( pert.watchLinkContainer );
	};
	
	/**
	 * 
	 */
	pert.setLastCheckTime = function(){
		
		var fn = function(){
			//console.log("in set last check time");
			var d = new Date();
			GM_setValue( "bbfch.config.topicWatch.lastWatchTime", ""+d.getTime() ); //make it a string, since there is a max size for integers in the config
			//console.log( d.getTime() );
		};
		setTimeout(fn, 50);
	}
	
	/**
	 * @return Number
	 */
	pert.getLastCheckTimeDiff = function(){
		var d = new Date();
		var lastWatchTime = parseInt( GM_getValue( "bbfch.config.topicWatch.lastWatchTime", 0 ), 10 );
		return (d.getTime() - lastWatchTime);
	}
	
	/**
	 * Initialize the UI stuff
	 *****************************/
	pert.init = function(){ 
		if (GM_getValue( "bbfch.config.saved" ) == true){
			pert.loadConfig();
		}
		pert.saveConfig();
		pert.makeToolbar();
		pert.collapsePosts();
		pert.addSideMenu();
		//console.log(window.location.pathname);
		if ( window.location.pathname == "/Community/posts.php" && !pert.inWatchList( gup( "topic" )) ){
			pert.addWatchThreadButton();
		} else if( pert.inWatchList( gup("topic") ) ) {
			//
			pert.addUnwatchThreadButton();
			pert.checkTopics();
		}
		//use setInterval to check the topics every x seconds
		if (pert.getLastCheckTimeDiff() > pert.config.topicWatch.watchInterval){
			pert.checkTopics();
			//console.log( pert.getLastCheckTimeDiff() );
		}
		var intervalCheck = function(){
			pert.checkTopics();
		}
		pert.topicWatchInterval = setInterval( intervalCheck, pert.config.topicWatch.watchInterval );
		pert.createWatchLinks();
	};
	
	pert.init();
};//end bbfch_init

/**
 * Get URL parameter by name
 * 
 * @param String name
 *********************************/
function gup( name )
{
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
}

/**
 * Toggle all posts
 * @param nsIDOMEvent event
 */
function toggleAllPosts(event){
	var allPosts = document.evaluate( "//span[@class='bbfch_post']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
	for (var p = 0; p < allPosts.snapshotLength; p++){
		var post = allPosts.snapshotItem(p);
			toggleLinkClick.call(post, event, this.toggleType);
	}
	event.preventDefault();
	return false;
}

/**
 * Handle a click event for a +/- toggle link
 * 
 * @param nsIDOMEvent event
 * @param String toggleType
 */
function toggleLinkClick(event, toggleType){
	if (toggleType != null){
		switch( toggleType ){
			case "expand":
				this.style.display = "block";
				var link = document.getElementById(this.id+"_toggleLink");
					link.style.backgroundPosition = "50% -16px";
			break;
			case "collapse":
				this.style.display = "none";
				var link = document.getElementById(this.id+"_toggleLink");
					link.style.backgroundPosition = "50% 0px";
			break;
		}
		
	} else {
		this.style.display = (this.style.display != "block") ? "block": "none";
		
		var link = document.getElementById(this.id+"_toggleLink");

		if (this.style.display == "block"){
			link.style.backgroundPosition = "50% -16px";
		} else {
			link.style.backgroundPosition = "50% 0px";
		}
	}
	event.preventDefault();
	return false;
}

/**
 * The default click handler for buttons
 * 
 *****************************************/
function defaultClickHandler(){
	var constants = pert.constants;
	var start = pert.contentArea.selectionStart;
	var end = pert.contentArea.selectionEnd;
	//console.log("Start: " + start + " End: " + end);
	//
	//get the selected text
	var selectedText = pert.contentArea.value.substr(start, end-start);
	//console.log(selectedText);
	if ( typeof( selectedText ) == "undefined" ){
		selectedText = "";
	}
	var newText = selectedText;
	var attributes = "";
	var attributeCount = 0;
		for (var a in this.attributes){
			var val = prompt("Enter value for " + a, this.attributes[a].defaultValue);
			if (val != null){//if they didn't click cancel
				attributes += val;
				attributeCount++;
				if ( attributeCount < this.attributes.length ){
					attributes+=" ";
				}
			} else {
				
				return false;
			}
		}
	
	switch( this.type ){
		case constants.TT_ENCLOSING:
			
			if (attributes != ""){
				newText = "[" + this.tag + " " + attributes + "]" + newText + "[/" + this.tag + "]";
			} else {
				newText = "[" + this.tag + "]" + newText + "[/" + this.tag + "]";
			}
			
		break;
		case constants.TT_SELFCLOSING:
			
			if (newText != ""){
				newText = "[" + this.tag + " " + attributes + "]"+ newText + "[/" + this.tag + "]";
			} else {
				newText = "[" + this.tag + " " + attributes + "]";
			}
			
		break;
	}
	
	pert.contentArea.value = pert.contentArea.value.substr(0, start) + newText + pert.contentArea.value.substr(end, pert.contentArea.value.length);
	pert.contentArea.focus();
}

/**
 * Inserts insertElement after afterElement
 * 
 * @param nsIDOMElement insertElement
 * @param nsIDOMElement afterElement
 *****************************************/
function insertAfter(insertElement, afterElement){
	afterElement.parentNode.insertBefore(insertElement, afterElement.nextSibling);
}

/**
 * Apply styles to an element using an object like {width:"100%", fontSize:"2em"}
 * 
 * @param Object styleObject
 * @param nsIDOMElement targetElement
 ****************************************/
function applyStyleObjectToElement( styleObject, targetElement ){
	for ( var styleName in styleObject ){
		targetElement.style[ styleName ] = styleObject[ styleName ];
		//console.log( "Applying Style: " + styleName + " = "+styleObject[ styleName ] );
	}
}

/**
 * attach events to the target element
 * 
 * @param Object eventsObject
 * @param nsIDOMElement targetElement
 ****************************************/
function attachEventsToElement( eventsObject, targetElement, objectName){
	if (eventsObject != null && targetElement){
		for ( var eventName in eventsObject ){
			if (eventName == "render"){ continue; }//skipped custom render event
			if (eventsObject.useCapture !== true && eventsObject.useCapture !== false){
				eventsObject.useCapture = false; //default to false
			}
			//console.log("adding "+eventName);
			eval("function customHandler_eventName_" + objectName + "(){ contentConfig.buttons[\"" + objectName + "\"].events[\"" + eventName + "\"].handler.call( contentConfig.buttons[\"" + objectName + "\"] ); }");
			targetElement.addEventListener(eventName, eval("customHandler_eventName_" + objectName), eventsObject[eventName].useCapture);
		}
	} else {
		//console.log("Attempt to attach events to non object, or events object is null");
	}
}

/**
 * @param Object buttonObject
 * @return nsIDOMElement
 ******************************/
function createButton( buttonObject, objectName ){
	var result = null;
	
	if ( buttonObject != null ){
		//using a div rather than a form button since you can do more style wise
		var result = document.createElement("div");
			pert.statics.buttonCount++;
			//result.id = "btn_pert_fch_"+statics.buttonCount;//generate an id for the button (i.e. btn_pert_fch_1)
			result.id = "btn_pfch_" + objectName
			
		
		//add button text
		result.appendChild( document.createTextNode( buttonObject.caption ) );
		attachEventsToElement(buttonObject.events, result, objectName);
		applyStyleObjectToElement( buttonObject.styles, result );
		
	}
	
	return result;
}

function clearNodes( targetID ){
    var Dom = YAHOO.util.Dom;
	var targetElement = Dom.get( targetID );

	if ( targetElement ){
		while( targetElement.firstChild != null ){//strip all nodes out
			targetElement.removeChild( targetElement.firstChild );
		}
		return true;
	}
	return false;
}

/**
 * Check if the array contains the supplied value
 * @param mixed val
 */
Array.prototype.contains = function(val){
	for ( i = 0; i < this.length; i++ ){
		if ( this[i] == val ){
			return true;
		}
	}
}

//if(!console) { var console = {}; console.log = function(v){/*alert(v);*/} };//if there's no console defined, make a primitive one